package service

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"strings"
	"tool/model"
	"tool/utils"

	"gitee.com/xuesongtao/protoc-go-valid/log"
	"gitee.com/xuesongtao/protoc-go-valid/valid"
)

// handleJson2Struct 将 json 转 struct
func handleJson2Struct(filedName, formatJsonStr string, outBuf *strings.Builder, otherStruct *[]string) {
	log.Infof("filedName: %s, formatJsonStr: %s", filedName, formatJsonStr)
	outBuf.WriteString(fmt.Sprintf("%s %s %s {\n", utils.CodeKeyWordFont("type"), filedName, utils.CodeKeyWordFont("struct")))
	dataRune := []rune(formatJsonStr)
	lastIndex := len(dataRune) - 1
	for i := 0; i < lastIndex; i++ {
		val := dataRune[i]
		if val == '{' || val == ',' || val == '\n' || val == '\t' {
			continue
		}

		// 解析key, 如 "a": "1"
		jsonFiledBuf := new(strings.Builder)
		if val == '"' {
			i++
			for i <= lastIndex {
				v := dataRune[i]
				// 字段结束的 "
				if v == '"' {
					i += 3 // 直接找到字段值
					break
				}
				jsonFiledBuf.WriteRune(v)
				i++
			}
		}

		// 解析val
		// 1. 字符串
		// 2. 对象
		// 3. 数组
		// 4. 数字
		filedName := utils.SplitStr2Title(jsonFiledBuf.String(), "_")
		switch dataRune[i] {
		case '"': // 字符串
			outBuf.WriteString(fmt.Sprintf("\t%s %s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("string"), jsonFiledBuf.String()))
			for i <= lastIndex { // 移动指针
				i++
				if dataRune[i] == '"' {
					break
				}
			}
		case '{': // 对象
			outBuf.WriteString(fmt.Sprintf("\t%s %s `json:\"%s,omitempty\"`\n", filedName, filedName, jsonFiledBuf.String()))
			// 截取需要待处理的结构体
			tmpBuf := new(strings.Builder)
			for i <= lastIndex {
				v := dataRune[i]
				tmpBuf.WriteRune(v)
				i++
				if v == '}' {
					break
				}
			}
			sonOutBuf := new(strings.Builder)
			handleJson2Struct(filedName, tmpBuf.String(), sonOutBuf, otherStruct)
			*otherStruct = append(*otherStruct, sonOutBuf.String())
		case '[': // 数组
			// 需要判断值得类型
			i += 4
			switch dataRune[i] {
			case '"': // 字符串
				outBuf.WriteString(fmt.Sprintf("\t%s []%s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("string"), jsonFiledBuf.String()))
				for i <= lastIndex { // 移动指针
					i++
					if dataRune[i] == ']' {
						break
					}
				}
			case '{':
				outBuf.WriteString(fmt.Sprintf("\t%s []%s `json:\"%s,omitempty\"`\n", filedName, filedName, jsonFiledBuf.String()))
				// 截取需要处理的结构体, 这里只处理一个就可以了
				tmpBuf := new(strings.Builder)
				for i <= lastIndex {
					v := dataRune[i]
					tmpBuf.WriteRune(v)
					if v == '}' {
						break
					}
					i++
				}
				sonOutBuf := new(strings.Builder)
				handleJson2Struct(filedName, tmpBuf.String(), sonOutBuf, otherStruct)
				*otherStruct = append(*otherStruct, sonOutBuf.String())
				for i <= lastIndex { // 移动指针
					i++
					if dataRune[i] == ']' {
						break
					}
				}
			default: // 数字型
				numBuf := new(strings.Builder)
				for i <= lastIndex {
					v := dataRune[i]
					i++
					if v == ']' {
						break
					}
					numBuf.WriteRune(dataRune[i])
				}

				if strings.Contains(numBuf.String(), ".") {
					outBuf.WriteString(fmt.Sprintf("\t%s []%s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("float64"), jsonFiledBuf.String()))
				} else {
					outBuf.WriteString(fmt.Sprintf("\t%s []%s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("int"), jsonFiledBuf.String()))
				}
			}
		default: // 数字
			numBuf := new(strings.Builder)
			for i <= lastIndex {
				v := dataRune[i]
				if v == ',' || v == '\n' {
					break
				}
				numBuf.WriteRune(dataRune[i])
				i++
			}

			if strings.Contains(numBuf.String(), ".") {
				outBuf.WriteString(fmt.Sprintf("\t%s %s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("float64"), jsonFiledBuf.String()))
			} else {
				outBuf.WriteString(fmt.Sprintf("\t%s %s `json:\"%s,omitempty\"`\n", filedName, utils.CodeKeyWordFont("int"), jsonFiledBuf.String()))
			}
		}
	}
	outBuf.WriteByte('}')
}

func Json2Struct(req *model.ReqData) *model.RespData {
	log.Infof("Json2Struct req: %+v", req)
	if err := valid.ValidateStruct(req); err != nil {
		log.Error("valid is failed, err: ", err)
		return model.GetResp(err.Error(), 1)
	}

	reqBytes := []byte(req.Data)
	if !json.Valid(reqBytes) {
		return model.GetResp("格式不正确", 1)
	}

	buf := new(strings.Builder)
	otherStruct := make([]string, 0, 5) // 保存嵌套结构体
	formatJsonBuf := new(bytes.Buffer)
	if err := json.Indent(formatJsonBuf, reqBytes, "", "\t"); err != nil {
		return model.GetResp(err.Error(), 1)
	}
	handleJson2Struct("GenerateStruct", formatJsonBuf.String(), buf, &otherStruct)

	// 处理嵌套 struct
	for _, v := range otherStruct {
		buf.WriteString("\n\n" + v)
	}
	return model.GetResp(buf.String())
}

func FormatJson(req *model.ReqData) *model.RespData {
	log.Infof("Json2Struct req: %+v", req)
	if err := valid.ValidateStruct(req); err != nil {
		log.Error("valid is failed, err: ", err)
		return model.GetResp(err.Error(), 1)
	}

	reqBytes := []byte(req.Data)
	if !json.Valid(reqBytes) {
		return model.GetResp("格式不正确", 1)
	}

	formatJsonBuf := new(bytes.Buffer)
	if err := json.Indent(formatJsonBuf, reqBytes, "", "\t"); err != nil {
		return model.GetResp(err.Error(), 1)
	}
	return model.GetResp(formatJsonBuf.String())
}

func Md5(req *model.ReqData) *model.RespData {
	log.Infof("Md5 req: %+v", req)
	if err := valid.ValidateStruct(req); err != nil {
		log.Error("valid is failed, err: ", err)
		return model.GetResp(err.Error(), 1)
	}

	md5Obj := md5.New()
	if _, err := md5Obj.Write([]byte(req.Data)); err != nil {
		return model.GetResp("处理失败", 1)
	}
	return model.GetResp(fmt.Sprintf("%x", md5Obj.Sum(nil)))
}
